﻿using System.IO;
using System.Text;

namespace Sex
{
    public partial class Sex : System.Web.UI.Page
    {
        public static class Hex
        {
            const bool Show16BitChars = false;
            const bool Show8BitChars = true;
            const bool ShowIBMchars = false;

            public static string ToHex1(int b)
            {
                string HexChars = "0123456789abcdef";
                return HexChars[b].ToString();
            }
            public static string ToHex(byte b)
            {
                return Hex.ToHex1(b / 16) + Hex.ToHex1(b % 16);
            }
            public static string ToHex(int b)
            {
                return Hex.ToHex((byte)(b / 256)) + Hex.ToHex((byte)(b % 256));
            }
            public static string ToHex(string s)
            {
                string HexChars = "";
                for (int i = 0; i < s.Length; i++)
                {
                    HexChars += "0x" + Hex.ToHex((byte)s[i]) + " ";
                }
                return HexChars;
            }
            private static byte[] GetBuffer(string s)
            {
                byte[] buffer = new byte[s.Length * 2];
                for (int i = 0; i < s.Length; i++)
                {
                    int b;
                    try
                    {
                        b = char.ConvertToUtf32(s, i);
                    }
                    catch
                    {
                        b = 65635;
                    }
                    buffer[2 * i] = (byte)(b / 256);
                    buffer[2 * i + 1] = (byte)(b % 256);
                }
                return buffer;
            }
            public static string ToChar(int b)
            {
                if (b < 32) return (ShowIBMchars ? "&#x25a" + Hex.ToHex1(b) + ";" : "&#x00b7;");
                else return ((char)b).ToString();
            }
            public static string ToUtf8(byte[] b)
            {
                if (((int)b[0] * 256 + (int)b[1]) < 32) return (ShowIBMchars ? "&#x25a" + Hex.ToHex1((char)b[1]) + ";" : "&#x00b7;");
                else return (new UTF8Encoding()).GetString(b);
            }
            public static string Dump(string FilePathAbsolute)
            {
                FileInfo fi = new FileInfo(FilePathAbsolute);
                int FileLength = (int)(fi.Length % 65536);
                BinaryReader binReader = new BinaryReader(File.Open(FilePathAbsolute, FileMode.Open, FileAccess.Read));
                byte[] buffer = new byte[FileLength];
                int ReadBytes = binReader.Read(buffer, 0, FileLength);
                binReader.Close();
                return Hex.Dump(buffer);
            }
            public static string Highlight(string Text, bool HighlightControls, bool HighlightForeign)
            {
                if (HighlightControls) return "<span class='HexCtrl'>" + Text + "</span>";
                else if (HighlightForeign) return "<span class='Hex8'>" + Text + "</span>";
                else return Text;
            }
            public static string Highlight(string Text, byte ToDisplay)
            {
                bool HighlightControls = false;
                bool HighlightForeign = false;
                if (ToDisplay < 32) HighlightControls = true;
                if (ToDisplay > 127) HighlightForeign = true;
                return Highlight(Text, HighlightControls, HighlightForeign);
            }
            public static string Dump(byte[] b)
            {
                string s = "";
                int PageCount = b.Length / 256; if (b.Length % 256 != 0) PageCount++;
                if (PageCount > 16) PageCount = 16;
                for (int p = 0; p < PageCount; p++)
                {
                    s += "<span class='HexContent'>" + Hex.ToHex((byte)p) + "</span><span class='HexCaption'> 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f" + (Show8BitChars ? "  0123456789abcdef" : "") + (Show16BitChars ? "  01234567" : "") + "</span>\r\n";
                    for (int r = 0; r < 16; r++)
                    {
                        string prefix = "<span class='HexCaption'>" + Hex.ToHex1(r) + "0</span> ";
                        string line_hex = "";
                        string line_char = "";
                        string line_char2 = "";
                        byte[] line_char20 = { 0, 0 };
                        for (int c = 0; c < 16; c++)
                        {
                            int index = p * 256 + r * 16 + c;
                            if (index == b.Length)
                            {
                                line_hex = line_hex.PadRight(16 * 3, ' ');
                                line_char = line_char + "".PadRight(16 - c, ' ');
                                s += prefix + line_hex + (Show8BitChars ? " " + Untag(line_char) : "") + (Show16BitChars ? "  " + Untag(line_char2) : "") + "\r\n";
                                goto for_end;
                            }
                            byte ToDisplay = b[index];
                            string strHex = ToHex(ToDisplay);
                            string strChar = ToChar(ToDisplay);
                            line_hex += Highlight(strHex,ToDisplay) + " ";
                            line_char += Highlight(Untag(strChar), ToDisplay);
                            line_char20[index % 2] = ToDisplay;
                            if (index % 2 == 1)
                            {
                                line_char2 += Untag(ToUtf8(line_char20));
                            }
                        }
                        s += prefix + line_hex + (Show8BitChars ? " " + line_char : "") + (Show16BitChars ? "  " + line_char2 : "") + "\r\n";
                    }
                    s += "\r\n";
                }
            for_end:
                return s;
            }
        }
    }
}